home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-11-19  |  14.1 KB  |  648 lines

  1. #ifndef lint‚þ®ŸîSid = "$Id: parse.c,v 1.9 1998/11/19 10:41:13 lhecking Exp $";
  2. #endif
  3.  
  4. /* GNUPLOT - parse.c */
  5.  
  6. /*[
  7.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and
  12.  * that both that copyright notice and this permission notice appear
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the complete modified source code.  Modifications are to
  17.  * be distributed as patches to the released version.  Permission to
  18.  * distribute binaries produced by compiling modified sources is granted,
  19.  * provided you
  20.  *   1. distribute the corresponding source modifications from the
  21.  *    released version in the form of a patch file along with the binaries,
  22.  *   2. add special version identification to distinguish your version
  23.  *    in addition to the base release version number,
  24.  *   3. provide your name and address as the primary contact for the
  25.  *    support of your modified version, and
  26.  *   4. retain our contact information in regard to use of the base
  27.  *    software.
  28.  * Permission to distribute the released version of the source code along
  29.  * with corresponding source modifications in the form of a patch file is
  30.  * granted with same provisions 2 through 4 for binary distributions.
  31.  *
  32.  * This software is provided "as is" without express or implied warranty
  33.  * to the extent permitted by applicable law.
  34. ]*/
  35.  
  36. #include <signal.h>
  37. #include "plot.h"
  38. #include "help.h"
  39. #include <setjmp.h>
  40.  
  41. RETSIGTYPE fpe __PROTO((int an_int));
  42. static void extend_at __PROTO((void));
  43. static union argument *add_action __PROTO((enum operators sf_index));
  44. static void express __PROTO((void));
  45. static void xterm __PROTO((void));
  46. static void aterm __PROTO((void));
  47. static void bterm __PROTO((void));
  48. static void cterm __PROTO((void));
  49. static void dterm __PROTO((void));
  50. static void eterm __PROTO((void));
  51. static void fterm __PROTO((void));
  52. static void gterm __PROTO((void));
  53. static void hterm __PROTO((void));
  54. static void factor __PROTO((void));
  55. static void xterms __PROTO((void));
  56. static void aterms __PROTO((void));
  57. static void bterms __PROTO((void));
  58. static void cterms __PROTO((void));
  59. static void dterms __PROTO((void));
  60. static void eterms __PROTO((void));
  61. static void fterms __PROTO((void));
  62. static void gterms __PROTO((void));
  63. static void hterms __PROTO((void));
  64. static void iterms __PROTO((void));
  65. static void unary __PROTO((void));
  66.  
  67. static struct at_type *at = NULL;
  68. static int at_size = 0;
  69. #if defined(_Windows) && !defined(WIN32)
  70. static jmp_buf far fpe_env;
  71. #else
  72. static jmp_buf fpe_env;
  73. #endif
  74.  
  75. #define dummy (struct value *) 0
  76.  
  77. RETSIGTYPE fpe(an_int)
  78. int an_int;
  79. {
  80. #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386)
  81.     /* thanks to lotto@wjh12.UUCP for telling us about this  */
  82.     _fpreset();
  83. #endif
  84.  
  85. #ifdef OS2
  86.     (void) signal(an_int, SIG_ACK);
  87. #else
  88.     (void) signal(SIGFPE, (sigfunc) fpe);
  89. #endif
  90.     undefined = TRUE;
  91.     longjmp(fpe_env, TRUE);
  92. }
  93.  
  94.  
  95. #ifdef apollo
  96. #include <apollo/base.h>
  97. #include <apollo/pfm.h>
  98. #include <apollo/fault.h>
  99.  
  100. /*
  101.  * On an Apollo, the OS can signal a couple errors that are not mapped into
  102.  * SIGFPE, namely signalling NaN and branch on an unordered comparison.  I
  103.  * suppose there are others, but none of these are documented, so I handle
  104.  * them as they arise. 
  105.  *
  106.  * Anyway, we need to catch these faults and signal SIGFPE. 
  107.  */
  108.  
  109. pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
  110. {
  111.     kill(getpid(), SIGFPE);
  112.     return pfm_$continue_fault_handling;
  113. }
  114.  
  115. apollo_pfm_catch()
  116. {
  117.     status_$t status;
  118.     pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
  119.                  apollo_sigfpe, &status);
  120.     pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
  121.                  apollo_sigfpe, &status);
  122. }
  123. #endif
  124.  
  125.  
  126. void evaluate_at(at_ptr, val_ptr)
  127. struct at_type *at_ptr;
  128. struct value *val_ptr;
  129. {
  130.     double temp;
  131.  
  132.     undefined = FALSE;
  133.     errno = 0;
  134.     reset_stack();
  135.  
  136. #ifndef DOSX286
  137.     if (setjmp(fpe_env))
  138.     return;            /* just bail out */
  139.     (void) signal(SIGFPE, (sigfunc) fpe);
  140. #endif
  141.  
  142.     execute_at(at_ptr);
  143.  
  144. #ifndef DOSX286
  145.     (void) signal(SIGFPE, SIG_DFL);
  146. #endif
  147.  
  148.     if (errno == EDOM || errno == ERANGE) {
  149.     undefined = TRUE;
  150.     } else if (!undefined) {    /* undefined (but not errno) may have been set by matherr */
  151.     (void) pop(val_ptr);
  152.     check_stack();
  153.     /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
  154.     temp = real(val_ptr);
  155.     if (temp > VERYLARGE || temp < -VERYLARGE) {
  156.         undefined = TRUE;
  157.     }
  158.     }
  159. #if defined(NeXT) || defined(ultrix)
  160.     /*
  161.      * linux was able to fit curves which NeXT gave up on -- traced it to
  162.      * silently returning NaN for the undefined cases and plowing ahead
  163.      * I can force that behavior this way.  (0.0/0.0 generates NaN)
  164.      */
  165.     if (undefined && (errno == EDOM || errno == ERANGE)) {    /* corey@cac */
  166.     undefined = FALSE;
  167.     errno = 0;
  168.     Gcomplex(val_ptr, 0.0 / 0.0, 0.0 / 0.0);
  169.     }
  170. #endif /* NeXT || ultrix */
  171. }
  172.  
  173.  
  174. struct value *
  175.  const_express(valptr)
  176. struct value *valptr;
  177. {
  178.     register int tkn = c_token;
  179.  
  180.     if (END_OF_COMMAND)
  181.     int_error("constant expression required", c_token);
  182.  
  183.     /* div - no dummy variables in a constant expression */
  184.     dummy_func = NULL;
  185.  
  186.     evaluate_at(temp_at(), valptr);    /* run it and send answer back */
  187.     if (undefined) {
  188.     int_error("undefined value", tkn);
  189.     }
  190.     return (valptr);
  191. }
  192.  
  193.  
  194. /* if dummy_dunc == NULL on entry, do not attempt to compile dummy variables
  195.  * - div
  196.  */
  197. struct at_type *
  198.  temp_at()
  199. {
  200.     /* build a static action table and return its
  201.      * pointer */
  202.  
  203.     if (at != NULL) {
  204.     free(at);
  205.     at = NULL;
  206.     }
  207.     at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
  208.  
  209.     at->a_count = 0;        /* reset action table !!! */
  210.     at_size = MAX_AT_LEN;
  211.     express();
  212.     return (at);
  213. }
  214.  
  215.  
  216. /* build an action table, put it in dynamic memory, and return its pointer */
  217.  
  218. struct at_type *
  219.  perm_at()
  220. {
  221.     register struct at_type *at_ptr;
  222.     unsigned int len;
  223.  
  224.     (void) temp_at();
  225.     len = sizeof(struct at_type) +
  226.      (int) (at->a_count - MAX_AT_LEN) * (int) sizeof(struct at_entry);
  227.     at_ptr = (struct at_type *) gp_realloc(at, (unsigned long) len, "perm_at");
  228.     at = NULL;            /* invalidate at pointer */
  229.     return (at_ptr);
  230. }
  231.  
  232. static void extend_at()
  233. {
  234.     int newsize = sizeof(struct at_type) + at_size * sizeof(struct at_entry);
  235.  
  236.     at = gp_realloc(at, newsize, "extend_at");
  237.     at_size += MAX_AT_LEN;
  238.     FPRINTF((stderr, "Extending at size to %d\n", at_size));
  239. }
  240.  
  241. /* moved from eval.c, the function is only called from this module */
  242. static union argument *
  243.  add_action(sf_index)
  244. enum operators sf_index;    /* index of p-code function */
  245. {
  246.     if (at->a_count >= at_size) {
  247.     extend_at();
  248.     }
  249.     at->actions[at->a_count].index = sf_index;
  250.     return (&(at->actions[at->a_count++].arg));
  251. }
  252.  
  253.  
  254. static void express()
  255. {                /* full expressions */
  256.     xterm();
  257.     xterms();
  258. }
  259.  
  260. static void xterm()
  261. {                /* ? : expressions */
  262.     aterm();
  263.     aterms();
  264. }
  265.  
  266.  
  267. static void aterm()
  268. {
  269.     bterm();
  270.     bterms();
  271. }
  272.  
  273.  
  274. static void bterm()
  275. {
  276.     cterm();
  277.     cterms();
  278. }
  279.  
  280.  
  281. static void cterm()
  282. {
  283.     dterm();
  284.     dterms();
  285. }
  286.  
  287.  
  288. static void dterm()
  289. {
  290.     eterm();
  291.     eterms();
  292. }
  293.  
  294.  
  295. static void eterm()
  296. {
  297.     fterm();
  298.     fterms();
  299. }
  300.  
  301.  
  302. static void fterm()
  303. {
  304.     gterm();
  305.     gterms();
  306. }
  307.  
  308.  
  309. static void gterm()
  310. {
  311.     hterm();
  312.     hterms();
  313. }
  314.  
  315.  
  316. static void hterm()
  317. {
  318.     unary();            /* - things */
  319.     iterms();            /* * / % */
  320. }
  321.  
  322.  
  323. static void factor()
  324. {
  325.     if (equals(c_token, "(")) {
  326.     c_token++;
  327.     express();
  328.     if (!equals(c_token, ")"))
  329.         int_error("')' expected", c_token);
  330.     c_token++;
  331.     } else if (equals(c_token, "$")) {
  332.     struct value a;
  333.     if (!isanumber(++c_token))
  334.         int_error("Column number expected", c_token);
  335.     convert(&a, c_token++);
  336.     if (a.type != INTGR || a.v.int_val < 0)
  337.         int_error("Positive integer expected", c_token);
  338.     add_action(DOLLARS)->v_arg = a;
  339.     } else if (isanumber(c_token)) {
  340.     /* work around HP 9000S/300 HP-UX 9.10 cc limitation ... */
  341. #if defined(__hpux) && defined(__hp9000s300) && !defined(__GNUC__)
  342.     union argument *foo = add_action(PUSHC);
  343.     convert(&(foo->v_arg), c_token);
  344. #else
  345.     convert(&(add_action(PUSHC)->v_arg), c_token);
  346. #endif
  347.     c_token++;
  348.     } else if (isletter(c_token)) {
  349.     if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) {
  350.         enum operators value = standard(c_token);
  351.         if (value) {    /* it's a standard function */
  352.         c_token += 2;
  353.         express();
  354.         if (equals(c_token, ",")) {
  355.             while (equals(c_token, ",")) {
  356.             c_token += 1;
  357.             express();
  358.             }
  359.         }
  360.         if (!equals(c_token, ")"))
  361.             int_error("')' expected", c_token);
  362.         c_token++;
  363.         (void) add_action(value);
  364.         } else {
  365.         enum operators call_type = (int) CALL;
  366.         int tok = c_token;
  367.         c_token += 2;
  368.         express();
  369.         if (equals(c_token, ",")) {
  370.             struct value num_params;
  371.             num_params.type = INTGR;
  372.             num_params.v.int_val = 1;
  373.             while (equals(c_token, ",")) {
  374.             num_params.v.int_val += 1;
  375.             c_token += 1;
  376.             express();
  377.             }
  378.             add_action(PUSHC)->v_arg = num_params;
  379.             call_type = (int) CALLN;
  380.         }
  381.         if (!equals(c_token, ")"))
  382.             int_error("')' expected", c_token);
  383.         c_token++;
  384.         add_action(call_type)->udf_arg = add_udf(tok);
  385.         }
  386.         /* dummy_func==NULL is a flag to say no dummy variables active */
  387.     } else if (dummy_func) {
  388.         if (equals(c_token, c_dummy_var[0])) {
  389.         c_token++;
  390.         add_action(PUSHD1)->udf_arg = dummy_func;
  391.         } else if (equals(c_token, c_dummy_var[1])) {
  392.         c_token++;
  393.         add_action(PUSHD2)->udf_arg = dummy_func;
  394.         } else {
  395.         int i, param = 0;
  396.         for (i = 2; i < MAX_NUM_VAR; i++) {
  397.             if (equals(c_token, c_dummy_var[i])) {
  398.             struct value num_params;
  399.             num_params.type = INTGR;
  400.             num_params.v.int_val = i;
  401.             param = 1;
  402.             c_token++;
  403.             add_action(PUSHC)->v_arg = num_params;
  404.             add_action(PUSHD)->udf_arg = dummy_func;
  405.             break;
  406.             }
  407.         }
  408.         if (!param) {    /* defined variable */
  409.             add_action(PUSH)->udv_arg = add_udv(c_token);
  410.             c_token++;
  411.         }
  412.         }
  413.         /* its a variable, with no dummies active - div */
  414.     } else {
  415.         add_action(PUSH)->udv_arg = add_udv(c_token);
  416.         c_token++;
  417.     }
  418.     }
  419.     /* end if letter */
  420.     else
  421.     int_error("invalid expression ", c_token);
  422.  
  423.     /* add action code for ! (factorial) operator */
  424.     while (equals(c_token, "!")) {
  425.     c_token++;
  426.     (void) add_action(FACTORIAL);
  427.     }
  428.     /* add action code for ** operator */
  429.     if (equals(c_token, "**")) {
  430.     c_token++;
  431.     unary();
  432.     (void) add_action(POWER);
  433.     }
  434. }
  435.  
  436.  
  437.  
  438. static void xterms()
  439. {
  440.     /* create action code for ? : expressions */
  441.  
  442.     if (equals(c_token, "?")) {
  443.     register int savepc1, savepc2;
  444.     register union argument *argptr1, *argptr2;
  445.     c_token++;
  446.     savepc1 = at->a_count;
  447.     argptr1 = add_action(JTERN);
  448.     express();
  449.     if (!equals(c_token, ":"))
  450.         int_error("expecting ':'", c_token);
  451.     c_token++;
  452.     savepc2 = at->a_count;
  453.     argptr2 = add_action(JUMP);
  454.     argptr1->j_arg = at->a_count - savepc1;
  455.     express();
  456.     argptr2->j_arg = at->a_count - savepc2;
  457.     }
  458. }
  459.  
  460.  
  461. static void aterms()
  462. {
  463.     /* create action codes for || operator */
  464.  
  465.     while (equals(c_token, "||")) {
  466.     register int savepc;
  467.     register union argument *argptr;
  468.     c_token++;
  469.     savepc = at->a_count;
  470.     argptr = add_action(JUMPNZ);    /* short-circuit if already
  471.                      * TRUE */
  472.     aterm();
  473.     argptr->j_arg = at->a_count - savepc;    /* offset for jump */
  474.     (void) add_action(BOOLE);
  475.     }
  476. }
  477.  
  478.  
  479. static void bterms()
  480. {
  481.     /* create action code for && operator */
  482.  
  483.     while (equals(c_token, "&&")) {
  484.     register int savepc;
  485.     register union argument *argptr;
  486.     c_token++;
  487.     savepc = at->a_count;
  488.     argptr = add_action(JUMPZ);    /* short-circuit if already
  489.                      * FALSE */
  490.     bterm();
  491.     argptr->j_arg = at->a_count - savepc;    /* offset for jump */
  492.     (void) add_action(BOOLE);
  493.     }
  494. }
  495.  
  496.  
  497. static void cterms()
  498. {
  499.     /* create action code for | operator */
  500.  
  501.     while (equals(c_token, "|")) {
  502.     c_token++;
  503.     cterm();
  504.     (void) add_action(BOR);
  505.     }
  506. }
  507.  
  508.  
  509. static void dterms()
  510. {
  511.     /* create action code for ^ operator */
  512.  
  513.     while (equals(c_token, "^")) {
  514.     c_token++;
  515.     dterm();
  516.     (void) add_action(XOR);
  517.     }
  518. }
  519.  
  520.  
  521. static void eterms()
  522. {
  523.     /* create action code for & operator */
  524.  
  525.     while (equals(c_token, "&")) {
  526.     c_token++;
  527.     eterm();
  528.     (void) add_action(BAND);
  529.     }
  530. }
  531.  
  532.  
  533. static void fterms()
  534. {
  535.     /* create action codes for == and !=
  536.      * operators */
  537.  
  538.     while (TRUE) {
  539.     if (equals(c_token, "==")) {
  540.         c_token++;
  541.         fterm();
  542.         (void) add_action(EQ);
  543.     } else if (equals(c_token, "!=")) {
  544.         c_token++;
  545.         fterm();
  546.         (void) add_action(NE);
  547.     } else
  548.         break;
  549.     }
  550. }
  551.  
  552.  
  553. static void gterms()
  554. {
  555.     /* create action code for < > >= or <=
  556.      * operators */
  557.  
  558.     while (TRUE) {
  559.     /* I hate "else if" statements */
  560.     if (equals(c_token, ">")) {
  561.         c_token++;
  562.         gterm();
  563.         (void) add_action(GT);
  564.     } else if (equals(c_token, "<")) {
  565.         c_token++;
  566.         gterm();
  567.         (void) add_action(LT);
  568.     } else if (equals(c_token, ">=")) {
  569.         c_token++;
  570.         gterm();
  571.         (void) add_action(GE);
  572.     } else if (equals(c_token, "<=")) {
  573.         c_token++;
  574.         gterm();
  575.         (void) add_action(LE);
  576.     } else
  577.         break;
  578.     }
  579.  
  580. }
  581.  
  582.  
  583.  
  584. static void hterms()
  585. {
  586.     /* create action codes for + and - operators */
  587.  
  588.     while (TRUE) {
  589.     if (equals(c_token, "+")) {
  590.         c_token++;
  591.         hterm();
  592.         (void) add_action(PLUS);
  593.     } else if (equals(c_token, "-")) {
  594.         c_token++;
  595.         hterm();
  596.         (void) add_action(MINUS);
  597.     } else
  598.         break;
  599.     }
  600. }
  601.  
  602.  
  603. static void iterms()
  604. {
  605.     /* add action code for * / and % operators */
  606.  
  607.     while (TRUE) {
  608.     if (equals(c_token, "*")) {
  609.         c_token++;
  610.         unary();
  611.         (void) add_action(MULT);
  612.     } else if (equals(c_token, "/")) {
  613.         c_token++;
  614.         unary();
  615.         (void) add_action(DIV);
  616.     } else if (equals(c_token, "%")) {
  617.         c_token++;
  618.         unary();
  619.         (void) add_action(MOD);
  620.     } else
  621.         break;
  622.     }
  623. }
  624.  
  625.  
  626. static void unary()
  627. {
  628.     /* add code for unary operators */
  629.  
  630.     if (equals(c_token, "!")) {
  631.     c_token++;
  632.     unary();
  633.     (void) add_action(LNOT);
  634.     } else if (equals(c_token, "~")) {
  635.     c_token++;
  636.     unary();
  637.     (void) add_action(BNOT);
  638.     } else if (equals(c_token, "-")) {
  639.     c_token++;
  640.     unary();
  641.     (void) add_action(UMINUS);
  642.     } else if (equals(c_token, "+")) {    /* unary + is no-op */
  643.     c_token++;
  644.     unary();
  645.     } else
  646.     factor();
  647. }
  648.